﻿namespace NetFx.AGIL
{
  using System;
  using System.Reflection;
  using System.Reflection.Emit;
  using System.Collections;
  using System.Collections.Generic;
  using System.Text;
  using System.IO;


  [Flags]
  public enum Conditions:int
  {
    Unknown = 0x00000000,
    Equal = 0x00000001,
    Null = 0x00000001,
    NotNull = 0x00000002,
    Always = 0x00000003,
    False = 0x00000004,
    True = 0x00000005,
    GreaterThan = 0x00000006,
    LessThan = 0x00000007,
    EqualOrGreaterThan = 0x00000008,
    EqualOrLessThan = 0x00000009,
    Different = 0x0000000A,

    Unsigned = 0x10,

  }
  [Flags]
  public enum Calculations:int
  {
    Unknown = 0x00,
    Negative = 0x01,
    Add = 0x02,
    Substract = 0x03,
    Multiply = 0x04,
    Divide = 0x05,
    Reminder = 0x06,
    Not = 0x07,
    And = 0x08,
    Or = 0x09,
    Xor = 0x0A,
    ShiftLeft = 0x0B,
    ShiftRight = 0x0C,

    Unsigned = 0x10,
    ThrowIfOverflow = 0x20,
  }

  [Flags]
  public enum Comparisions:int
  {
    Unknown = 0x00,
    Equal = 0x01,
    GreaterThan = 0x02,
    LessThan = 0x03,
    Unsigned = 0x10,
  }

  [Flags]
  public enum Convertions:int
  {
    Unknown = 0x00,
    ToSignedNative = 0x01,
    ToUnsignedNative = 0x02,
    ToSigned8 = 0x03,
    ToSigned16 = 0x04,
    ToSigned32 = 0x05,
    ToSigned64 = 0x06,
    ToUnsigned8 = 0x07,
    ToUnsigned16 = 0x08,
    ToUnsigned32 = 0x09,
    ToUnsigned64 = 0x0A,
    ToFloat = 0x0B,
    ToDouble = 0x0C,
    Checked = 0x10,
    Unsigned = 0x20,
  }

  [Flags]
  public enum Prefixes:int
  {
    Unknown = 0x00,
    P1 = 0x01,
    P2 = 0x02,
    P3 = 0x03,
    P4 = 0x04,
    P5 = 0x05,
    P6 = 0x06,
    P7 = 0x07,
    Ref = 0x08,
  }

  /// <summary>
  /// Agil操作。
  /// 一个Agil操作包括IL操作码，
  /// 以及IL的操作数。它相当
  /// 于一条已经实例化的指令。
  /// </summary>
  public class AgilOperation
  {
    #region Agil Opcodes
    #region Defs
    public static readonly AgilOperation Nop;
    public static readonly AgilOperation Break;
    public static readonly AgilOperation Ldarg_0;
    public static readonly AgilOperation Ldarg_1;
    public static readonly AgilOperation Ldarg_2;
    public static readonly AgilOperation Ldarg_3;
    public static readonly AgilOperation Ldloc_0;
    public static readonly AgilOperation Ldloc_1;
    public static readonly AgilOperation Ldloc_2;
    public static readonly AgilOperation Ldloc_3;
    public static readonly AgilOperation Stloc_0;
    public static readonly AgilOperation Stloc_1;
    public static readonly AgilOperation Stloc_2;
    public static readonly AgilOperation Stloc_3;
    public static readonly AgilOperation Ldarg_S;
    public static readonly AgilOperation Ldarga_S;
    public static readonly AgilOperation Starg_S;
    public static readonly AgilOperation Ldloc_S;
    public static readonly AgilOperation Ldloca_S;
    public static readonly AgilOperation Stloc_S;
    public static readonly AgilOperation Ldnull;
    public static readonly AgilOperation Ldc_I4_M1;
    public static readonly AgilOperation Ldc_I4_0;
    public static readonly AgilOperation Ldc_I4_1;
    public static readonly AgilOperation Ldc_I4_2;
    public static readonly AgilOperation Ldc_I4_3;
    public static readonly AgilOperation Ldc_I4_4;
    public static readonly AgilOperation Ldc_I4_5;
    public static readonly AgilOperation Ldc_I4_6;
    public static readonly AgilOperation Ldc_I4_7;
    public static readonly AgilOperation Ldc_I4_8;
    public static readonly AgilOperation Ldc_I4_S;
    public static readonly AgilOperation Ldc_I4;
    public static readonly AgilOperation Ldc_I8;
    public static readonly AgilOperation Ldc_R4;
    public static readonly AgilOperation Ldc_R8;
    public static readonly AgilOperation Dup;
    public static readonly AgilOperation Pop;
    public static readonly AgilOperation Jmp;
    public static readonly AgilOperation Call;
    public static readonly AgilOperation Calli;
    public static readonly AgilOperation Ret;
    public static readonly AgilOperation Br_S;
    public static readonly AgilOperation Brfalse_S;
    public static readonly AgilOperation Brtrue_S;
    public static readonly AgilOperation Beq_S;
    public static readonly AgilOperation Bge_S;
    public static readonly AgilOperation Bgt_S;
    public static readonly AgilOperation Ble_S;
    public static readonly AgilOperation Blt_S;
    public static readonly AgilOperation Bne_Un_S;
    public static readonly AgilOperation Bge_Un_S;
    public static readonly AgilOperation Bgt_Un_S;
    public static readonly AgilOperation Ble_Un_S;
    public static readonly AgilOperation Blt_Un_S;
    public static readonly AgilOperation Br;
    public static readonly AgilOperation Brfalse;
    public static readonly AgilOperation Brtrue;
    public static readonly AgilOperation Beq;
    public static readonly AgilOperation Bge;
    public static readonly AgilOperation Bgt;
    public static readonly AgilOperation Ble;
    public static readonly AgilOperation Blt;
    public static readonly AgilOperation Bne_Un;
    public static readonly AgilOperation Bge_Un;
    public static readonly AgilOperation Bgt_Un;
    public static readonly AgilOperation Ble_Un;
    public static readonly AgilOperation Blt_Un;
    public static readonly AgilOperation Switch;
    public static readonly AgilOperation Ldind_I1;
    public static readonly AgilOperation Ldind_U1;
    public static readonly AgilOperation Ldind_I2;
    public static readonly AgilOperation Ldind_U2;
    public static readonly AgilOperation Ldind_I4;
    public static readonly AgilOperation Ldind_U4;
    public static readonly AgilOperation Ldind_I8;
    public static readonly AgilOperation Ldind_I;
    public static readonly AgilOperation Ldind_R4;
    public static readonly AgilOperation Ldind_R8;
    public static readonly AgilOperation Ldind_Ref;
    public static readonly AgilOperation Stind_Ref;
    public static readonly AgilOperation Stind_I1;
    public static readonly AgilOperation Stind_I2;
    public static readonly AgilOperation Stind_I4;
    public static readonly AgilOperation Stind_I8;
    public static readonly AgilOperation Stind_R4;
    public static readonly AgilOperation Stind_R8;
    public static readonly AgilOperation Add;
    public static readonly AgilOperation Sub;
    public static readonly AgilOperation Mul;
    public static readonly AgilOperation Div;
    public static readonly AgilOperation Div_Un;
    public static readonly AgilOperation Rem;
    public static readonly AgilOperation Rem_Un;
    public static readonly AgilOperation And;
    public static readonly AgilOperation Or;
    public static readonly AgilOperation Xor;
    public static readonly AgilOperation Shl;
    public static readonly AgilOperation Shr;
    public static readonly AgilOperation Shr_Un;
    public static readonly AgilOperation Neg;
    public static readonly AgilOperation Not;
    public static readonly AgilOperation Conv_I1;
    public static readonly AgilOperation Conv_I2;
    public static readonly AgilOperation Conv_I4;
    public static readonly AgilOperation Conv_I8;
    public static readonly AgilOperation Conv_R4;
    public static readonly AgilOperation Conv_R8;
    public static readonly AgilOperation Conv_U4;
    public static readonly AgilOperation Conv_U8;
    public static readonly AgilOperation Callvirt;
    public static readonly AgilOperation Cpobj;
    public static readonly AgilOperation Ldobj;
    public static readonly AgilOperation Ldstr;
    public static readonly AgilOperation Newobj;
    public static readonly AgilOperation Castclass;
    public static readonly AgilOperation Isinst;
    public static readonly AgilOperation Conv_R_Un;
    public static readonly AgilOperation Unbox;
    public static readonly AgilOperation Unbox_Any;
    public static readonly AgilOperation Throw;
    public static readonly AgilOperation Ldfld;
    public static readonly AgilOperation Ldflda;
    public static readonly AgilOperation Stfld;
    public static readonly AgilOperation Ldsfld;
    public static readonly AgilOperation Ldsflda;
    public static readonly AgilOperation Stsfld;
    public static readonly AgilOperation Stobj;
    public static readonly AgilOperation Conv_Ovf_I1_Un;
    public static readonly AgilOperation Conv_Ovf_I2_Un;
    public static readonly AgilOperation Conv_Ovf_I4_Un;
    public static readonly AgilOperation Conv_Ovf_I8_Un;
    public static readonly AgilOperation Conv_Ovf_U1_Un;
    public static readonly AgilOperation Conv_Ovf_U2_Un;
    public static readonly AgilOperation Conv_Ovf_U4_Un;
    public static readonly AgilOperation Conv_Ovf_U8_Un;
    public static readonly AgilOperation Conv_Ovf_I_Un;
    public static readonly AgilOperation Conv_Ovf_U_Un;
    public static readonly AgilOperation Box;
    public static readonly AgilOperation Newarr;
    public static readonly AgilOperation Ldlen;
    public static readonly AgilOperation Ldelema;
    public static readonly AgilOperation Ldelem_I1;
    public static readonly AgilOperation Ldelem_U1;
    public static readonly AgilOperation Ldelem_I2;
    public static readonly AgilOperation Ldelem_U2;
    public static readonly AgilOperation Ldelem_I4;
    public static readonly AgilOperation Ldelem_U4;
    public static readonly AgilOperation Ldelem_I8;
    public static readonly AgilOperation Ldelem_I;
    public static readonly AgilOperation Ldelem_R4;
    public static readonly AgilOperation Ldelem_R8;
    public static readonly AgilOperation Ldelem_Ref;
    public static readonly AgilOperation Ldelem_Any;
    public static readonly AgilOperation Stelem_I;
    public static readonly AgilOperation Stelem_I1;
    public static readonly AgilOperation Stelem_I2;
    public static readonly AgilOperation Stelem_I4;
    public static readonly AgilOperation Stelem_I8;
    public static readonly AgilOperation Stelem_R4;
    public static readonly AgilOperation Stelem_R8;
    public static readonly AgilOperation Stelem_Ref;
    public static readonly AgilOperation Stelem_Any;
    public static readonly AgilOperation Conv_Ovf_I1;
    public static readonly AgilOperation Conv_Ovf_U1;
    public static readonly AgilOperation Conv_Ovf_I2;
    public static readonly AgilOperation Conv_Ovf_U2;
    public static readonly AgilOperation Conv_Ovf_I4;
    public static readonly AgilOperation Conv_Ovf_U4;
    public static readonly AgilOperation Conv_Ovf_I8;
    public static readonly AgilOperation Conv_Ovf_U8;
    public static readonly AgilOperation Refanyval;
    public static readonly AgilOperation Ckfinite;
    public static readonly AgilOperation Mkrefany;
    public static readonly AgilOperation Ldtoken;
    public static readonly AgilOperation Conv_U2;
    public static readonly AgilOperation Conv_U1;
    public static readonly AgilOperation Conv_I;
    public static readonly AgilOperation Conv_Ovf_I;
    public static readonly AgilOperation Conv_Ovf_U;
    public static readonly AgilOperation Add_Ovf;
    public static readonly AgilOperation Add_Ovf_Un;
    public static readonly AgilOperation Mul_Ovf;
    public static readonly AgilOperation Mul_Ovf_Un;
    public static readonly AgilOperation Sub_Ovf;
    public static readonly AgilOperation Sub_Ovf_Un;
    public static readonly AgilOperation Endfinally;
    public static readonly AgilOperation Leave;
    public static readonly AgilOperation Leave_S;
    public static readonly AgilOperation Stind_I;
    public static readonly AgilOperation Conv_U;
    public static readonly AgilOperation Prefix7;
    public static readonly AgilOperation Prefix6;
    public static readonly AgilOperation Prefix5;
    public static readonly AgilOperation Prefix4;
    public static readonly AgilOperation Prefix3;
    public static readonly AgilOperation Prefix2;
    public static readonly AgilOperation Prefix1;
    public static readonly AgilOperation Prefixref;
    public static readonly AgilOperation Arglist;
    public static readonly AgilOperation Ceq;
    public static readonly AgilOperation Cgt;
    public static readonly AgilOperation Cgt_Un;
    public static readonly AgilOperation Clt;
    public static readonly AgilOperation Clt_Un;
    public static readonly AgilOperation Ldftn;
    public static readonly AgilOperation Ldvirtftn;
    public static readonly AgilOperation Ldarg;
    public static readonly AgilOperation Ldarga;
    public static readonly AgilOperation Starg;
    public static readonly AgilOperation Ldloc;
    public static readonly AgilOperation Ldloca;
    public static readonly AgilOperation Stloc;
    public static readonly AgilOperation Localloc;
    public static readonly AgilOperation Endfilter;
    public static readonly AgilOperation Unaligned;
    public static readonly AgilOperation Volatile;
    public static readonly AgilOperation Tailcall;
    public static readonly AgilOperation Initobj;
    public static readonly AgilOperation Cpblk;
    public static readonly AgilOperation Initblk;
    public static readonly AgilOperation Rethrow;
    public static readonly AgilOperation Sizeof;
    public static readonly AgilOperation Refanytype;


    public static readonly AgilOperation Try;
    public static readonly AgilOperation TryEnd;
    public static readonly AgilOperation Filter;
    public static readonly AgilOperation Catch;
    public static readonly AgilOperation Fault;
    public static readonly AgilOperation Finally;

    #endregion
    #region Refs
    /// <summary>
    /// 所有的AGIL指令构成的表。
    /// </summary>
    public static readonly AgilOperation[] Agils =
    {
      Nop           = AgilOperation.of(MsilOpcode.Nop           ),
      Break         = AgilOperation.of(MsilOpcode.Break         ),
      Ldarg_0       = AgilOperation.of(MsilOpcode.Ldarg_0       ),
      Ldarg_1       = AgilOperation.of(MsilOpcode.Ldarg_1       ),
      Ldarg_2       = AgilOperation.of(MsilOpcode.Ldarg_2       ),
      Ldarg_3       = AgilOperation.of(MsilOpcode.Ldarg_3       ),
      Ldloc_0       = AgilOperation.of(MsilOpcode.Ldloc_0       ),
      Ldloc_1       = AgilOperation.of(MsilOpcode.Ldloc_1       ),
      Ldloc_2       = AgilOperation.of(MsilOpcode.Ldloc_2       ),
      Ldloc_3       = AgilOperation.of(MsilOpcode.Ldloc_3       ),
      Stloc_0       = AgilOperation.of(MsilOpcode.Stloc_0       ),
      Stloc_1       = AgilOperation.of(MsilOpcode.Stloc_1       ),
      Stloc_2       = AgilOperation.of(MsilOpcode.Stloc_2       ),
      Stloc_3       = AgilOperation.of(MsilOpcode.Stloc_3       ),
      Ldarg_S       = AgilOperation.of(MsilOpcode.Ldarg_S       ),
      Ldarga_S      = AgilOperation.of(MsilOpcode.Ldarga_S      ),
      Starg_S       = AgilOperation.of(MsilOpcode.Starg_S       ),
      Ldloc_S       = AgilOperation.of(MsilOpcode.Ldloc_S       ),
      Ldloca_S      = AgilOperation.of(MsilOpcode.Ldloca_S      ),
      Stloc_S       = AgilOperation.of(MsilOpcode.Stloc_S       ),
      Ldnull        = AgilOperation.of(MsilOpcode.Ldnull        ),
      Ldc_I4_M1     = AgilOperation.of(MsilOpcode.Ldc_I4_M1     ),
      Ldc_I4_0      = AgilOperation.of(MsilOpcode.Ldc_I4_0      ),
      Ldc_I4_1      = AgilOperation.of(MsilOpcode.Ldc_I4_1      ),
      Ldc_I4_2      = AgilOperation.of(MsilOpcode.Ldc_I4_2      ),
      Ldc_I4_3      = AgilOperation.of(MsilOpcode.Ldc_I4_3      ),
      Ldc_I4_4      = AgilOperation.of(MsilOpcode.Ldc_I4_4      ),
      Ldc_I4_5      = AgilOperation.of(MsilOpcode.Ldc_I4_5      ),
      Ldc_I4_6      = AgilOperation.of(MsilOpcode.Ldc_I4_6      ),
      Ldc_I4_7      = AgilOperation.of(MsilOpcode.Ldc_I4_7      ),
      Ldc_I4_8      = AgilOperation.of(MsilOpcode.Ldc_I4_8      ),
      Ldc_I4_S      = AgilOperation.of(MsilOpcode.Ldc_I4_S      ),
      Ldc_I4        = AgilOperation.of(MsilOpcode.Ldc_I4        ),
      Ldc_I8        = AgilOperation.of(MsilOpcode.Ldc_I8        ),
      Ldc_R4        = AgilOperation.of(MsilOpcode.Ldc_R4        ),
      Ldc_R8        = AgilOperation.of(MsilOpcode.Ldc_R8        ),
      Dup           = AgilOperation.of(MsilOpcode.Dup           ),
      Pop           = AgilOperation.of(MsilOpcode.Pop           ),
      Jmp           = AgilOperation.of(MsilOpcode.Jmp           ),
      Call          = AgilOperation.of(MsilOpcode.Call          ),
      Calli         = AgilOperation.of(MsilOpcode.Calli         ),
      Ret           = AgilOperation.of(MsilOpcode.Ret           ),
      Br_S          = AgilOperation.of(MsilOpcode.Br_S          ),
      Brfalse_S     = AgilOperation.of(MsilOpcode.Brfalse_S     ),
      Brtrue_S      = AgilOperation.of(MsilOpcode.Brtrue_S      ),
      Beq_S         = AgilOperation.of(MsilOpcode.Beq_S         ),
      Bge_S         = AgilOperation.of(MsilOpcode.Bge_S         ),
      Bgt_S         = AgilOperation.of(MsilOpcode.Bgt_S         ),
      Ble_S         = AgilOperation.of(MsilOpcode.Ble_S         ),
      Blt_S         = AgilOperation.of(MsilOpcode.Blt_S         ),
      Bne_Un_S      = AgilOperation.of(MsilOpcode.Bne_Un_S      ),
      Bge_Un_S      = AgilOperation.of(MsilOpcode.Bge_Un_S      ),
      Bgt_Un_S      = AgilOperation.of(MsilOpcode.Bgt_Un_S      ),
      Ble_Un_S      = AgilOperation.of(MsilOpcode.Ble_Un_S      ),
      Blt_Un_S      = AgilOperation.of(MsilOpcode.Blt_Un_S      ),
      Br            = AgilOperation.of(MsilOpcode.Br            ),
      Brfalse       = AgilOperation.of(MsilOpcode.Brfalse       ),
      Brtrue        = AgilOperation.of(MsilOpcode.Brtrue        ),
      Beq           = AgilOperation.of(MsilOpcode.Beq           ),
      Bge           = AgilOperation.of(MsilOpcode.Bge           ),
      Bgt           = AgilOperation.of(MsilOpcode.Bgt           ),
      Ble           = AgilOperation.of(MsilOpcode.Ble           ),
      Blt           = AgilOperation.of(MsilOpcode.Blt           ),
      Bne_Un        = AgilOperation.of(MsilOpcode.Bne_Un        ),
      Bge_Un        = AgilOperation.of(MsilOpcode.Bge_Un        ),
      Bgt_Un        = AgilOperation.of(MsilOpcode.Bgt_Un        ),
      Ble_Un        = AgilOperation.of(MsilOpcode.Ble_Un        ),
      Blt_Un        = AgilOperation.of(MsilOpcode.Blt_Un        ),
      Switch        = AgilOperation.of(MsilOpcode.Switch        ),
      Ldind_I1      = AgilOperation.of(MsilOpcode.Ldind_I1      ),
      Ldind_U1      = AgilOperation.of(MsilOpcode.Ldind_U1      ),
      Ldind_I2      = AgilOperation.of(MsilOpcode.Ldind_I2      ),
      Ldind_U2      = AgilOperation.of(MsilOpcode.Ldind_U2      ),
      Ldind_I4      = AgilOperation.of(MsilOpcode.Ldind_I4      ),
      Ldind_U4      = AgilOperation.of(MsilOpcode.Ldind_U4      ),
      Ldind_I8      = AgilOperation.of(MsilOpcode.Ldind_I8      ),
      Ldind_I       = AgilOperation.of(MsilOpcode.Ldind_I       ),
      Ldind_R4      = AgilOperation.of(MsilOpcode.Ldind_R4      ),
      Ldind_R8      = AgilOperation.of(MsilOpcode.Ldind_R8      ),
      Ldind_Ref     = AgilOperation.of(MsilOpcode.Ldind_Ref     ),
      Stind_Ref     = AgilOperation.of(MsilOpcode.Stind_Ref     ),
      Stind_I1      = AgilOperation.of(MsilOpcode.Stind_I1      ),
      Stind_I2      = AgilOperation.of(MsilOpcode.Stind_I2      ),
      Stind_I4      = AgilOperation.of(MsilOpcode.Stind_I4      ),
      Stind_I8      = AgilOperation.of(MsilOpcode.Stind_I8      ),
      Stind_R4      = AgilOperation.of(MsilOpcode.Stind_R4      ),
      Stind_R8      = AgilOperation.of(MsilOpcode.Stind_R8      ),
      Add           = AgilOperation.of(MsilOpcode.Add           ),
      Sub           = AgilOperation.of(MsilOpcode.Sub           ),
      Mul           = AgilOperation.of(MsilOpcode.Mul           ),
      Div           = AgilOperation.of(MsilOpcode.Div           ),
      Div_Un        = AgilOperation.of(MsilOpcode.Div_Un        ),
      Rem           = AgilOperation.of(MsilOpcode.Rem           ),
      Rem_Un        = AgilOperation.of(MsilOpcode.Rem_Un        ),
      And           = AgilOperation.of(MsilOpcode.And           ),
      Or            = AgilOperation.of(MsilOpcode.Or            ),
      Xor           = AgilOperation.of(MsilOpcode.Xor           ),
      Shl           = AgilOperation.of(MsilOpcode.Shl           ),
      Shr           = AgilOperation.of(MsilOpcode.Shr           ),
      Shr_Un        = AgilOperation.of(MsilOpcode.Shr_Un        ),
      Neg           = AgilOperation.of(MsilOpcode.Neg           ),
      Not           = AgilOperation.of(MsilOpcode.Not           ),
      Conv_I1       = AgilOperation.of(MsilOpcode.Conv_I1       ),
      Conv_I2       = AgilOperation.of(MsilOpcode.Conv_I2       ),
      Conv_I4       = AgilOperation.of(MsilOpcode.Conv_I4       ),
      Conv_I8       = AgilOperation.of(MsilOpcode.Conv_I8       ),
      Conv_R4       = AgilOperation.of(MsilOpcode.Conv_R4       ),
      Conv_R8       = AgilOperation.of(MsilOpcode.Conv_R8       ),
      Conv_U4       = AgilOperation.of(MsilOpcode.Conv_U4       ),
      Conv_U8       = AgilOperation.of(MsilOpcode.Conv_U8       ),
      Callvirt      = AgilOperation.of(MsilOpcode.Callvirt      ),
      Cpobj         = AgilOperation.of(MsilOpcode.Cpobj         ),
      Ldobj         = AgilOperation.of(MsilOpcode.Ldobj         ),
      Ldstr         = AgilOperation.of(MsilOpcode.Ldstr         ),
      Newobj        = AgilOperation.of(MsilOpcode.Newobj        ),
      Castclass     = AgilOperation.of(MsilOpcode.Castclass     ),
      Isinst        = AgilOperation.of(MsilOpcode.Isinst        ),
      Conv_R_Un     = AgilOperation.of(MsilOpcode.Conv_R_Un     ),
      Unbox         = AgilOperation.of(MsilOpcode.Unbox         ),
      Unbox_Any     = AgilOperation.of(MsilOpcode.Unbox_Any     ),
      Throw         = AgilOperation.of(MsilOpcode.Throw         ),
      Ldfld         = AgilOperation.of(MsilOpcode.Ldfld         ),
      Ldflda        = AgilOperation.of(MsilOpcode.Ldflda        ),
      Stfld         = AgilOperation.of(MsilOpcode.Stfld         ),
      Ldsfld        = AgilOperation.of(MsilOpcode.Ldsfld        ),
      Ldsflda       = AgilOperation.of(MsilOpcode.Ldsflda       ),
      Stsfld        = AgilOperation.of(MsilOpcode.Stsfld        ),
      Stobj         = AgilOperation.of(MsilOpcode.Stobj         ),
      Conv_Ovf_I1_Un= AgilOperation.of(MsilOpcode.Conv_Ovf_I1_Un),
      Conv_Ovf_I2_Un= AgilOperation.of(MsilOpcode.Conv_Ovf_I2_Un),
      Conv_Ovf_I4_Un= AgilOperation.of(MsilOpcode.Conv_Ovf_I4_Un),
      Conv_Ovf_I8_Un= AgilOperation.of(MsilOpcode.Conv_Ovf_I8_Un),
      Conv_Ovf_U1_Un= AgilOperation.of(MsilOpcode.Conv_Ovf_U1_Un),
      Conv_Ovf_U2_Un= AgilOperation.of(MsilOpcode.Conv_Ovf_U2_Un),
      Conv_Ovf_U4_Un= AgilOperation.of(MsilOpcode.Conv_Ovf_U4_Un),
      Conv_Ovf_U8_Un= AgilOperation.of(MsilOpcode.Conv_Ovf_U8_Un),
      Conv_Ovf_I_Un = AgilOperation.of(MsilOpcode.Conv_Ovf_I_Un ),
      Conv_Ovf_U_Un = AgilOperation.of(MsilOpcode.Conv_Ovf_U_Un ),
      Box           = AgilOperation.of(MsilOpcode.Box           ),
      Newarr        = AgilOperation.of(MsilOpcode.Newarr        ),
      Ldlen         = AgilOperation.of(MsilOpcode.Ldlen         ),
      Ldelema       = AgilOperation.of(MsilOpcode.Ldelema       ),
      Ldelem_I1     = AgilOperation.of(MsilOpcode.Ldelem_I1     ),
      Ldelem_U1     = AgilOperation.of(MsilOpcode.Ldelem_U1     ),
      Ldelem_I2     = AgilOperation.of(MsilOpcode.Ldelem_I2     ),
      Ldelem_U2     = AgilOperation.of(MsilOpcode.Ldelem_U2     ),
      Ldelem_I4     = AgilOperation.of(MsilOpcode.Ldelem_I4     ),
      Ldelem_U4     = AgilOperation.of(MsilOpcode.Ldelem_U4     ),
      Ldelem_I8     = AgilOperation.of(MsilOpcode.Ldelem_I8     ),
      Ldelem_I      = AgilOperation.of(MsilOpcode.Ldelem_I      ),
      Ldelem_R4     = AgilOperation.of(MsilOpcode.Ldelem_R4     ),
      Ldelem_R8     = AgilOperation.of(MsilOpcode.Ldelem_R8     ),
      Ldelem_Ref    = AgilOperation.of(MsilOpcode.Ldelem_Ref    ),
      Ldelem_Any    = AgilOperation.of(MsilOpcode.Ldelem_Any    ),
      Stelem_I      = AgilOperation.of(MsilOpcode.Stelem_I      ),
      Stelem_I1     = AgilOperation.of(MsilOpcode.Stelem_I1     ),
      Stelem_I2     = AgilOperation.of(MsilOpcode.Stelem_I2     ),
      Stelem_I4     = AgilOperation.of(MsilOpcode.Stelem_I4     ),
      Stelem_I8     = AgilOperation.of(MsilOpcode.Stelem_I8     ),
      Stelem_R4     = AgilOperation.of(MsilOpcode.Stelem_R4     ),
      Stelem_R8     = AgilOperation.of(MsilOpcode.Stelem_R8     ),
      Stelem_Ref    = AgilOperation.of(MsilOpcode.Stelem_Ref    ),
      Stelem_Any    = AgilOperation.of(MsilOpcode.Stelem_Any    ),
      Conv_Ovf_I1   = AgilOperation.of(MsilOpcode.Conv_Ovf_I1   ),
      Conv_Ovf_U1   = AgilOperation.of(MsilOpcode.Conv_Ovf_U1   ),
      Conv_Ovf_I2   = AgilOperation.of(MsilOpcode.Conv_Ovf_I2   ),
      Conv_Ovf_U2   = AgilOperation.of(MsilOpcode.Conv_Ovf_U2   ),
      Conv_Ovf_I4   = AgilOperation.of(MsilOpcode.Conv_Ovf_I4   ),
      Conv_Ovf_U4   = AgilOperation.of(MsilOpcode.Conv_Ovf_U4   ),
      Conv_Ovf_I8   = AgilOperation.of(MsilOpcode.Conv_Ovf_I8   ),
      Conv_Ovf_U8   = AgilOperation.of(MsilOpcode.Conv_Ovf_U8   ),
      Refanyval     = AgilOperation.of(MsilOpcode.Refanyval     ),
      Ckfinite      = AgilOperation.of(MsilOpcode.Ckfinite      ),
      Mkrefany      = AgilOperation.of(MsilOpcode.Mkrefany      ),
      Ldtoken       = AgilOperation.of(MsilOpcode.Ldtoken       ),
      Conv_U2       = AgilOperation.of(MsilOpcode.Conv_U2       ),
      Conv_U1       = AgilOperation.of(MsilOpcode.Conv_U1       ),
      Conv_I        = AgilOperation.of(MsilOpcode.Conv_I        ),
      Conv_Ovf_I    = AgilOperation.of(MsilOpcode.Conv_Ovf_I    ),
      Conv_Ovf_U    = AgilOperation.of(MsilOpcode.Conv_Ovf_U    ),
      Add_Ovf       = AgilOperation.of(MsilOpcode.Add_Ovf       ),
      Add_Ovf_Un    = AgilOperation.of(MsilOpcode.Add_Ovf_Un    ),
      Mul_Ovf       = AgilOperation.of(MsilOpcode.Mul_Ovf       ),
      Mul_Ovf_Un    = AgilOperation.of(MsilOpcode.Mul_Ovf_Un    ),
      Sub_Ovf       = AgilOperation.of(MsilOpcode.Sub_Ovf       ),
      Sub_Ovf_Un    = AgilOperation.of(MsilOpcode.Sub_Ovf_Un    ),
      Endfinally    = AgilOperation.of(MsilOpcode.Endfinally    ),
      Leave         = AgilOperation.of(MsilOpcode.Leave         ),
      Leave_S       = AgilOperation.of(MsilOpcode.Leave_S       ),
      Stind_I       = AgilOperation.of(MsilOpcode.Stind_I       ),
      Conv_U        = AgilOperation.of(MsilOpcode.Conv_U        ),
      Prefix7       = AgilOperation.of(MsilOpcode.Prefix7       ),
      Prefix6       = AgilOperation.of(MsilOpcode.Prefix6       ),
      Prefix5       = AgilOperation.of(MsilOpcode.Prefix5       ),
      Prefix4       = AgilOperation.of(MsilOpcode.Prefix4       ),
      Prefix3       = AgilOperation.of(MsilOpcode.Prefix3       ),
      Prefix2       = AgilOperation.of(MsilOpcode.Prefix2       ),
      Prefix1       = AgilOperation.of(MsilOpcode.Prefix1       ),
      Prefixref     = AgilOperation.of(MsilOpcode.Prefixref     ),
      Arglist       = AgilOperation.of(MsilOpcode.Arglist       ),
      Ceq           = AgilOperation.of(MsilOpcode.Ceq           ),
      Cgt           = AgilOperation.of(MsilOpcode.Cgt           ),
      Cgt_Un        = AgilOperation.of(MsilOpcode.Cgt_Un        ),
      Clt           = AgilOperation.of(MsilOpcode.Clt           ),
      Clt_Un        = AgilOperation.of(MsilOpcode.Clt_Un        ),
      Ldftn         = AgilOperation.of(MsilOpcode.Ldftn         ),
      Ldvirtftn     = AgilOperation.of(MsilOpcode.Ldvirtftn     ),
      Ldarg         = AgilOperation.of(MsilOpcode.Ldarg         ),
      Ldarga        = AgilOperation.of(MsilOpcode.Ldarga        ),
      Starg         = AgilOperation.of(MsilOpcode.Starg         ),
      Ldloc         = AgilOperation.of(MsilOpcode.Ldloc         ),
      Ldloca        = AgilOperation.of(MsilOpcode.Ldloca        ),
      Stloc         = AgilOperation.of(MsilOpcode.Stloc         ),
      Localloc      = AgilOperation.of(MsilOpcode.Localloc      ),
      Endfilter     = AgilOperation.of(MsilOpcode.Endfilter     ),
      Unaligned     = AgilOperation.of(MsilOpcode.Unaligned     ),
      Volatile      = AgilOperation.of(MsilOpcode.Volatile      ),
      Tailcall      = AgilOperation.of(MsilOpcode.Tailcall      ),
      Initobj       = AgilOperation.of(MsilOpcode.Initobj       ),
      Cpblk         = AgilOperation.of(MsilOpcode.Cpblk         ),
      Initblk       = AgilOperation.of(MsilOpcode.Initblk       ),
      Rethrow       = AgilOperation.of(MsilOpcode.Rethrow       ),
      Sizeof        = AgilOperation.of(MsilOpcode.Sizeof        ),
      Refanytype    = AgilOperation.of(MsilOpcode.Refanytype    ),



      Try           = AgilOperation.of(MsilOpcode.Try           ),
      TryEnd        = AgilOperation.of(MsilOpcode.TryEnd        ),
      Filter        = AgilOperation.of(MsilOpcode.Filter        ),
      Catch         = AgilOperation.of(MsilOpcode.Catch         ),
      Fault         = AgilOperation.of(MsilOpcode.Fault         ),
      Finally       = AgilOperation.of(MsilOpcode.Finally       ),

    };
    #endregion
    #endregion
    #region Consts
    public const char LabelSeparator = ';';
    #endregion
    #region Statics
    /// <summary>
    /// 初始化所有静态局字段。
    /// </summary>
    static AgilOperation()
    {
      if (Agils != null)
      {
          foreach (AgilOperation agil in Agils)
          {
            if (agil != null)
            {
              if (!NamingAgilTable.ContainsKey(agil.OpcodeName))
              {
                NamingAgilTable.Add(agil.OpcodeName, agil);
              }
              if (!OpcodingAgilTable.ContainsKey(agil.Opcode))
              {
                OpcodingAgilTable.Add(agil.Opcode, agil);
              }
            }
          }
      }
    }
    /// <summary>
    /// 所有的AGIL指令操作码以名称检索的表。
    /// </summary>
    public static readonly Hashtable NamingAgilTable = new Hashtable();
    /// <summary>
    /// 所有的AGIL指令操作码以Opcode值检索的表。
    /// </summary>
    public static readonly Hashtable OpcodingAgilTable = new Hashtable();
    /// <summary>
    /// 从BinaryReader读取AgilOperation。
    /// </summary>
    /// <param name="reader">二进制阅读器。</param>
    /// <param name="module">当前模块。</param>
    /// <param name="offset">当前偏移量。</param>
    /// <returns>完整的Agil操作。</returns>
    /// <remarks>
    /// 由于IL使用前缀码，我们可以分为两步读取指令。
    /// 先在指令集合中搜寻所有符合前缀的指令，如果
    /// 所得指令唯一（可能没有指令），那么取得这个
    /// 指令；如果指令不唯一，我们再读一个字节，
    /// 在剩余的集合中继续搜寻。
    /// </remarks>
    public static AgilOperation Read(BinaryReader reader,Module module,MethodBase method,long offset)
    {
      AgilOperation ret_agil = null;
      if (reader != null && reader.BaseStream.CanRead
        && (reader.BaseStream.Position < reader.BaseStream.Length))
      {
        List<AgilOperation> matchAgils = new List<AgilOperation>();
        byte firstOpcode = reader.ReadByte();

        for (int i = 0; i < Agils.Length; i++)
        {
          AgilOperation agil = Agils[i];
          if (agil != null && agil.IsOpcodeMatched(firstOpcode,true))
          {
            matchAgils.Add(agil);
          }
        }
        if (matchAgils.Count <= 0)
        {
          //throw new InvalidOperationException("No valid IL code found!");
        }
        else if (matchAgils.Count == 1)
        {
          AgilOperation agil = matchAgils[0];
          if (agil != null)
          {
            ret_agil = agil.Clone();
          }
          else
          {
            //throw new InvalidOperationException("No valid IL code found!");
          }
        }
        else if (reader.BaseStream.CanRead)
        {
          byte secondOpcode = reader.ReadByte();
          foreach (AgilOperation agil in matchAgils)
          {
            if (agil != null && agil.IsOpcodeMatched(secondOpcode, false))
            {
              //Found and duplicate the agil in template.
              ret_agil = agil.Clone();
              break;
            }
          }
        }

        //Found matched!
        if (ret_agil != null)
        {
          ret_agil.Read(reader,module, method, offset, false);
        }
      }
      return ret_agil;
    }
    /// <summary>
    /// 测试代码是否是实验用代码。
    /// </summary>
    public static bool IsILExperimental(byte firstByte)
    {
      return firstByte >= (byte)0xF0 && firstByte <= (byte)0xFB;
    }
    /// <summary>
    /// 测试代码是否是实验用代码。
    /// </summary>
    public static bool IsILExperimental(byte[] ilcode, uint firstByteIndex)
    {
      byte firstByte = ilcode[firstByteIndex];
      return firstByte >= (byte)0xF0 && firstByte <= (byte)0xFB;
    }
    /// <summary>
    /// 测试代码是否是标准代码。
    /// </summary>
    public static bool IsILStandardlized(byte firstByte)
    {
      return (firstByte >= (byte)0x00 && firstByte <= (byte)0xEF)
        || (firstByte >= (byte)0xFC && firstByte <= (byte)0xFF);
    }
    /// <summary>
    /// 测试代码是否是标准代码。
    /// </summary>
    public static bool IsILStandardlized(byte[] ilcode, uint firstByteIndex)
    {
      byte firstByte = ilcode[firstByteIndex];
      return (firstByte >= (byte)0x00 && firstByte <= (byte)0xEF)
        || (firstByte >= (byte)0xFC && firstByte <= (byte)0xFF);
    }

    #region ToTables
    public static Convertions  GetConvertion(AgilOperation agil)
    {
      Convertions con = Convertions.Unknown;
      if (agil != null)
      {
        if (agil.IsOpcodeMatched(AgilOperation.Conv_I))
        {
          con = Convertions.ToSignedNative;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_I))
        {
          con = Convertions.ToSignedNative | Convertions.Checked;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_I_Un))
        {
          con = Convertions.ToSignedNative | Convertions.Checked | Convertions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_U))
        {
          con = Convertions.ToUnsignedNative;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_U))
        {
          con = Convertions.ToUnsignedNative | Convertions.Checked;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_U_Un))
        {
          con = Convertions.ToUnsignedNative | Convertions.Checked | Convertions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_I1))
        {
          con = Convertions.ToSigned8;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_I))
        {
          con = Convertions.ToSigned8 | Convertions.Checked;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_I1_Un))
        {
          con = Convertions.ToSigned8 | Convertions.Checked | Convertions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_I2))
        {
          con = Convertions.ToSigned16;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_I2))
        {
          con = Convertions.ToSigned16 | Convertions.Checked;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_I2_Un))
        {
          con = Convertions.ToSigned16 | Convertions.Checked | Convertions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_I4))
        {
          con = Convertions.ToSigned32;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_I4))
        {
          con = Convertions.ToSigned32 | Convertions.Checked;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_I4_Un))
        {
          con = Convertions.ToSigned32 | Convertions.Checked | Convertions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_I8))
        {
          con = Convertions.ToSigned64;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_I8))
        {
          con = Convertions.ToSigned64 | Convertions.Checked;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_I8_Un))
        {
          con = Convertions.ToSigned64 | Convertions.Checked | Convertions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_U1))
        {
          con = Convertions.ToUnsigned8;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_U1))
        {
          con = Convertions.ToUnsigned8 | Convertions.Checked;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_U1_Un))
        {
          con = Convertions.ToUnsigned8 | Convertions.Checked | Convertions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_U2))
        {
          con = Convertions.ToUnsigned16;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_U2))
        {
          con = Convertions.ToUnsigned16 | Convertions.Checked;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_U2_Un))
        {
          con = Convertions.ToUnsigned16 | Convertions.Checked | Convertions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_U4))
        {
          con = Convertions.ToUnsigned32;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_U4))
        {
          con = Convertions.ToUnsigned32 | Convertions.Checked;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_U4_Un))
        {
          con = Convertions.ToUnsigned32 | Convertions.Checked | Convertions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_U8))
        {
          con = Convertions.ToUnsigned64;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_U8))
        {
          con = Convertions.ToUnsigned64 | Convertions.Checked;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_Ovf_U8_Un))
        {
          con = Convertions.ToUnsigned64 | Convertions.Checked | Convertions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_R_Un))
        {
          con = Convertions.ToFloat | Convertions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_R4))
        {
          con = Convertions.ToFloat;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Conv_R8))
        {
          con = Convertions.ToDouble;
        }
      }
      return con;
    }
    public static Prefixes     GetPrefix(AgilOperation agil)
    {
      Prefixes pre = Prefixes.Unknown;

      if (agil != null)
      {
        if (agil.IsOpcodeMatched(AgilOperation.Prefixref))
        {
          pre = Prefixes.Ref;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Prefix1))
        {
          pre = Prefixes.P1;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Prefix2))
        {
          pre = Prefixes.P2;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Prefix3))
        {
          pre = Prefixes.P3;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Prefix4))
        {
          pre = Prefixes.P4;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Prefix5))
        {
          pre = Prefixes.P5;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Prefix6))
        {
          pre = Prefixes.P6;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Prefix7))
        {
          pre = Prefixes.P7;
        }
      }

      return pre;
    }
    public static Comparisions GetComparision(AgilOperation agil)
    {
      Comparisions comp = Comparisions.Unknown;

      if (agil != null)
      {
        if (agil.IsOpcodeMatched(AgilOperation.Ceq))
        {
          comp = Comparisions.Equal;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Cgt))
        {
          comp = Comparisions.GreaterThan;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Clt))
        {
          comp = Comparisions.LessThan;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Cgt_Un))
        {
          comp = Comparisions.GreaterThan | Comparisions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Clt_Un))
        {
          comp = Comparisions.LessThan | Comparisions.Unsigned;
        }
      }
      return comp;
    }
    public static Calculations GetCalculation(AgilOperation agil)
    {
      Calculations calc = Calculations.Unknown;

      if (agil != null)
      {
        if (agil.IsOpcodeMatched(AgilOperation.Add))
        {
          calc = Calculations.Add;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Sub))
        {
          calc = Calculations.Substract;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Mul))
        {
          calc = Calculations.Multiply;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Div))
        {
          calc = Calculations.Divide;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Rem))
        {
          calc = Calculations.Reminder;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Neg))
        {
          calc = Calculations.Negative;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Not))
        {
          calc = Calculations.Not;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.And))
        {
          calc = Calculations.And;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Or))
        {
          calc = Calculations.Or;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Xor))
        {
          calc = Calculations.Xor;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Shl))
        {
          calc = Calculations.ShiftLeft;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Shr))
        {
          calc = Calculations.ShiftRight;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Div_Un))
        {
          calc = Calculations.Divide | Calculations.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Rem_Un))
        {
          calc = Calculations.Reminder | Calculations.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Shr_Un))
        {
          calc = Calculations.ShiftRight | Calculations.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Add_Ovf))
        {
          calc = Calculations.Add | Calculations.ThrowIfOverflow;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Sub_Ovf))
        {
          calc = Calculations.Substract | Calculations.ThrowIfOverflow;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Mul_Ovf))
        {
          calc = Calculations.Multiply | Calculations.ThrowIfOverflow;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Add_Ovf_Un))
        {
          calc = Calculations.Add | Calculations.ThrowIfOverflow | Calculations.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Sub_Ovf_Un))
        {
          calc = Calculations.Substract | Calculations.ThrowIfOverflow | Calculations.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Mul_Ovf_Un))
        {
          calc = Calculations.Multiply | Calculations.ThrowIfOverflow | Calculations.Unsigned;
        }
      }
      return calc;
    }
    public static Conditions   GetCondition(AgilOperation agil)
    {
      Conditions cond = Conditions.Unknown;

      if (agil != null)
      {
        if (agil.IsOpcodeMatched(AgilOperation.Br_S) || agil.IsOpcodeMatched(AgilOperation.Br))
        {
          cond = Conditions.Always;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Brtrue) || agil.IsOpcodeMatched(AgilOperation.Brtrue_S))
        {
          cond = Conditions.True;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Brfalse) || agil.IsOpcodeMatched(AgilOperation.Brfalse_S))
        {
          cond = Conditions.False;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Beq) || agil.IsOpcodeMatched(AgilOperation.Beq_S))
        {
          cond = Conditions.Equal;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Bge) || agil.IsOpcodeMatched(AgilOperation.Bge_S))
        {
          cond = Conditions.EqualOrGreaterThan;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Bgt) || agil.IsOpcodeMatched(AgilOperation.Bgt_S))
        {
          cond = Conditions.GreaterThan;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Ble) || agil.IsOpcodeMatched(AgilOperation.Ble_S))
        {
          cond = Conditions.EqualOrLessThan;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Blt) || agil.IsOpcodeMatched(AgilOperation.Blt_S))
        {
          cond = Conditions.LessThan;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Bne_Un) || agil.IsOpcodeMatched(AgilOperation.Bne_Un_S))
        {
          cond = Conditions.Different | Conditions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Bge_Un) || agil.IsOpcodeMatched(AgilOperation.Bge_Un_S))
        {
          cond = Conditions.EqualOrGreaterThan | Conditions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Bgt_Un) || agil.IsOpcodeMatched(AgilOperation.Bgt_Un_S))
        {
          cond = Conditions.GreaterThan | Conditions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Ble_Un) || agil.IsOpcodeMatched(AgilOperation.Ble_Un_S))
        {
          cond = Conditions.EqualOrLessThan | Conditions.Unsigned;
        }
        else if (agil.IsOpcodeMatched(AgilOperation.Blt_Un) || agil.IsOpcodeMatched(AgilOperation.Blt_Un_S))
        {
          cond = Conditions.LessThan | Conditions.Unsigned;
        }
      }

      return cond;
    }
    #endregion

    #region FromTables
    public static AgilOperation GetAgilTemplateOf(Convertions convertion)
    {
      AgilOperation op = null;

      bool ckd = ((convertion & Convertions.Checked) == Convertions.Checked);
      bool uns = ((convertion & Convertions.Unsigned) == Convertions.Unsigned);

      if (ckd)
      {
        #region Checked
        switch (convertion)
        {
          case Convertions.ToSignedNative:
            op = uns ? AgilOperation.Conv_Ovf_I_Un : AgilOperation.Conv_Ovf_I;
            break;
          case Convertions.ToUnsignedNative:
            op = uns ? AgilOperation.Conv_Ovf_U_Un : AgilOperation.Conv_Ovf_U;
            break;
          case Convertions.ToSigned8:
            op = uns ? AgilOperation.Conv_Ovf_I1_Un : AgilOperation.Conv_Ovf_I1;
            break;
          case Convertions.ToSigned16:
            op = uns ? AgilOperation.Conv_Ovf_I2_Un : AgilOperation.Conv_Ovf_I2;
            break;
          case Convertions.ToSigned32:
            op = uns ? AgilOperation.Conv_Ovf_I4_Un : AgilOperation.Conv_Ovf_I4;
            break;
          case Convertions.ToSigned64:
            op = uns ? AgilOperation.Conv_Ovf_I8_Un : AgilOperation.Conv_Ovf_I8;
            break;
          case Convertions.ToUnsigned8:
            op = uns ? AgilOperation.Conv_Ovf_U1_Un : AgilOperation.Conv_Ovf_U1;
            break;
          case Convertions.ToUnsigned16:
            op = uns ? AgilOperation.Conv_Ovf_U2_Un : AgilOperation.Conv_Ovf_U2;
            break;
          case Convertions.ToUnsigned32:
            op = uns ? AgilOperation.Conv_Ovf_U4_Un : AgilOperation.Conv_Ovf_U4;
            break;
          case Convertions.ToUnsigned64:
            op = uns ? AgilOperation.Conv_Ovf_U8_Un : AgilOperation.Conv_Ovf_U8;
            break;
        }
        #endregion
      }
      else
      {
        #region Unchecked
        switch (convertion)
        {
          case Convertions.ToSignedNative:
            op = AgilOperation.Conv_I;
            break;
          case Convertions.ToUnsignedNative:
            op = AgilOperation.Conv_U;
            break;
          case Convertions.ToSigned8:
            op = AgilOperation.Conv_I1;
            break;
          case Convertions.ToSigned16:
            op = AgilOperation.Conv_I2;
            break;
          case Convertions.ToSigned32:
            op = AgilOperation.Conv_I4;
            break;
          case Convertions.ToSigned64:
            op = AgilOperation.Conv_I8;
            break;
          case Convertions.ToUnsigned8:
            op = AgilOperation.Conv_U1;
            break;
          case Convertions.ToUnsigned16:
            op = AgilOperation.Conv_U2;
            break;
          case Convertions.ToUnsigned32:
            op = AgilOperation.Conv_U4;
            break;
          case Convertions.ToUnsigned64:
            op = AgilOperation.Conv_U8;
            break;
          case Convertions.ToFloat:
            op = uns ? AgilOperation.Conv_R_Un : AgilOperation.Conv_R4;
            break;
          case Convertions.ToDouble:
            op = AgilOperation.Conv_R8;
            break;
        }
        #endregion
      }

      return op;
    }
    public static AgilOperation GetAgilTemplateOf(Prefixes prefix)
    {
      AgilOperation op = null;

      switch (prefix)
      {
        case Prefixes.P1:
          op = AgilOperation.Prefix1;
          break;
        case Prefixes.P2:
          op = AgilOperation.Prefix2;
          break;
        case Prefixes.P3:
          op = AgilOperation.Prefix3;
          break;
        case Prefixes.P4:
          op = AgilOperation.Prefix4;
          break;
        case Prefixes.P5:
          op = AgilOperation.Prefix5;
          break;
        case Prefixes.P6:
          op = AgilOperation.Prefix6;
          break;
        case Prefixes.P7:
          op = AgilOperation.Prefix7;
          break;
        case Prefixes.Ref:
          op = AgilOperation.Prefixref;
          break;
      }

      return op;
    }
    public static AgilOperation GetAgilTemplateOf(Comparisions comparision)
    {
      AgilOperation op = null;

      bool uns = ((comparision &Comparisions.Unsigned)==Comparisions.Unsigned);

      comparision &= ~Comparisions.Unsigned;

      if (comparision == Comparisions.Equal)
      {
        op = AgilOperation.Ceq;
      }
      else
      {
        switch (comparision)
        {
          case Comparisions.GreaterThan:
            op = uns ? AgilOperation.Cgt_Un : AgilOperation.Cgt;
            break;
          case Comparisions.LessThan:
            op = uns ? AgilOperation.Clt_Un : AgilOperation.Clt;
            break;
        }

      }
      return op;
    }
    public static AgilOperation GetAgilTemplateOf(Calculations calculation)
    {
      AgilOperation op = null;
      bool uns = ((calculation & Calculations.Unsigned) == Calculations.Unsigned);
      bool ckd = ((calculation & Calculations.ThrowIfOverflow) == Calculations.ThrowIfOverflow);

      calculation &= ~Calculations.Unsigned;
      calculation &= ~Calculations.ThrowIfOverflow;

      if (ckd)
      {
        if (uns)
        {
          #region Unsigned and checked
          switch (calculation)
          {
            case Calculations.Add:
              op = AgilOperation.Add_Ovf;
              break;
            case Calculations.Substract:
              op = AgilOperation.Sub_Ovf;
              break;
            case Calculations.Multiply:
              op = AgilOperation.Mul_Ovf;
              break;
          }
          #endregion
        }
        else
        {
          #region Signed and checked
          switch (calculation)
          {
            case Calculations.Add:
              op = AgilOperation.Add_Ovf_Un;
              break;
            case Calculations.Substract:
              op = AgilOperation.Sub_Ovf_Un;
              break;
            case Calculations.Multiply:
              op = AgilOperation.Mul_Ovf_Un;
              break;
          }

          #endregion
        }
      }
      else
      {
        if (uns)
        {
          #region Unsigned and Unchecked
          switch (calculation)
          {
            case Calculations.Divide:
              op = AgilOperation.Div_Un;
              break;
            case Calculations.Reminder:
              op = AgilOperation.Rem_Un;
              break;
            case Calculations.ShiftRight:
              op = AgilOperation.Shr_Un;
              break;
          }
          #endregion
        }
        else
        {
          #region Signed and Unchecked
          switch (calculation)
          {
            case Calculations.Add:
              op = AgilOperation.Add;
              break;
            case Calculations.Substract:
              op = AgilOperation.Sub;
              break;
            case Calculations.Multiply:
              op = AgilOperation.Mul;
              break;
            case Calculations.Divide:
              op = AgilOperation.Div;
              break;
            case Calculations.Reminder:
              op = AgilOperation.Rem;
              break;
            case Calculations.Negative:
              op = AgilOperation.Neg;
              break;
            case Calculations.Not:
              op = AgilOperation.Not;
              break;
            case Calculations.And:
              op = AgilOperation.And;
              break;
            case Calculations.Or:
              op = AgilOperation.Or;
              break;
            case Calculations.Xor:
              op = AgilOperation.Xor;
              break;
            case Calculations.ShiftLeft:
              op = AgilOperation.Shl;
              break;
            case Calculations.ShiftRight:
              op = AgilOperation.Shr;
              break;
          }
          #endregion
        }
      }

      return op;
    }
    public static AgilOperation GetAgilTemplateOf(Conditions condition, bool shortForm)
    {
      AgilOperation op = null;

      bool uns = ((condition & Conditions.Unsigned) == Conditions.Unsigned);

      condition &= ~Conditions.Unsigned;

      if (uns)
      {
        #region Unsigned
        switch (condition)
        {
          case Conditions.Different:
            op = shortForm ? AgilOperation.Bne_Un_S : AgilOperation.Bne_Un;
            break;
          case Conditions.EqualOrGreaterThan:
            op = shortForm ? AgilOperation.Bge_Un_S : AgilOperation.Bge_Un;
            break;
          case Conditions.GreaterThan:
            op = shortForm ? AgilOperation.Bgt_Un_S : AgilOperation.Bgt_Un;
            break;
          case Conditions.EqualOrLessThan:
            op = shortForm ? AgilOperation.Ble_Un_S : AgilOperation.Ble_Un;
            break;
          case Conditions.LessThan:
            op = shortForm ? AgilOperation.Blt_Un_S : AgilOperation.Blt_Un;
            break;
        }
        #endregion
      }
      else
      {
        #region Signed/Unconditional
        switch (condition)
        {
          case Conditions.Always:
            op = shortForm ? AgilOperation.Br_S : AgilOperation.Br;
            break;
          case Conditions.True:
            op = shortForm ? AgilOperation.Brtrue_S : AgilOperation.Brtrue;
            break;
          case Conditions.False:
            op = shortForm ? AgilOperation.Brfalse_S : AgilOperation.Brfalse;
            break;
          case Conditions.Equal:
            op = shortForm ? AgilOperation.Beq_S : AgilOperation.Beq;
            break;
          case Conditions.EqualOrGreaterThan:
            op = shortForm ? AgilOperation.Bge_S : AgilOperation.Bge;
            break;
          case Conditions.GreaterThan:
            op = shortForm ? AgilOperation.Bgt_S: AgilOperation.Bgt;
            break;
          case Conditions.EqualOrLessThan:
            op = shortForm ? AgilOperation.Ble_S: AgilOperation.Ble;
            break;
          case Conditions.LessThan:
            op = shortForm ? AgilOperation.Blt_S: AgilOperation.Blt;
            break;
        }
        #endregion
      }
      return op;
    }
    #endregion

    /// <summary>
    /// 生成MSIL操作码对应的Agil。
    /// </summary>
    protected static AgilOperation of(MsilOpcode opcode)
    {
      return new AgilOperation(opcode);
    }
    /// <summary>
    /// 生成MSIL操作码对应的Agil，并设定操作数。
    /// </summary>
    protected static AgilOperation of(MsilOpcode opcode, object operand)
    {
      return new AgilOperation(opcode,operand);
    }
    /// <summary>
    /// 生成MSIL操作码对应的Agil，并设定操作数。
    /// </summary>
    protected static AgilOperation of(MsilOpcode opcode, object operand, int stringToken)
    {
      return new AgilOperation(opcode, operand,stringToken);
    }
    #endregion
    #region Fields
    /// <summary>
    /// IL操作码。
    /// </summary>
    /// <remarks>
    /// 如果没有特别的需要，建议在实例生成之后，不要改变这个字段。
    /// 然而由于可能存在不同的需要，此字段未标明为readonly。
    /// </remarks>
    protected MsilOpcode opcode;
    /// <summary>
    /// IL操作数（依照指令而定）。
    /// </summary>
    protected object operand = null;
    /// <summary>
    /// 字符串Token。
    /// 由于无法使用字符串获取字符串的Token，
    /// 只能在读取IL的时候将字符串
    /// 的Token记录下来。
    /// 不使用Hashtable，是因为
    /// 在不同的Module中可能出现
    /// 相同的字符串Token。
    /// </summary>
    protected int stringToken = 0;
    /// <summary>
    /// 记录Agil操作在IL代码流中的位置。
    /// </summary>
    protected long offset = 0;
    /// <summary>
    /// 当前指令所属的 MethodBase。
    /// </summary>
    protected MethodBase method = null;

    protected string labels = string.Empty;

    protected string variableName = string.Empty;


    protected Type[] pushStack = null;

    protected Type[] popStack = null;
    #endregion
    #region Properties
    /// <summary>
    /// 获取操作码第一字节。
    /// </summary>
    public virtual byte FirstByte
    {
      get
      {
        return opcode.FirstByte;      
      }
    }
    /// <summary>
    /// 获取操作码第二字节。
    /// </summary>
    public virtual byte SecondByte
    {
      get
      {
        return opcode.SecondByte;
      }
    }
    /// <summary>
    /// 判别当前操作是否是虚拟操作。
    /// </summary>
    public virtual bool IsFake
    {
      get
      {
        return this.opcode.IsFake;
      }
    }
    /// <summary>
    /// 获取IL操作码。
    /// </summary>
    /// <remarks>
    /// 如果操作码Size为1，则使用0xFF掩码。
    /// </remarks>
    public virtual short Opcode
    {
      get
      {
        return //opcode.Size <= 0 ? (short)0 : //Treat as NOP
          (opcode.Size == 1 ?(short) (opcode.Value & (short)0xFF) : opcode.Value);
      }
    }
    /// <summary>
    /// 获取对应的MsilOpcode。
    /// </summary>
    public virtual MsilOpcode MsilOpcode
    {
      get
      {
        return this.opcode;
      }
    }
    public virtual MsilOperandCat MsilOperandCat
    {
      get
      {
        return this.MsilOpcode.OperandCat;
      }
    }
    /// <summary>
    /// 获取操作码名称。
    /// </summary>
    public virtual string OpcodeName
    {
      get
      {
        return this.opcode.Name;
      }
    }
    /// <summary>
    /// 获取或者设置操作数。
    /// </summary>
    /// <remarks>
    /// Agil以Reflection对象为表达方式。
    /// 即在Operand中所表现的尽可能是
    /// Type，MethodInfo等对象，而不是
    /// 它们对应的Token。尤其是从指令
    /// 序列反射时，Agil会对Token进行
    /// 自动的转换，转换为Type等类型
    /// 的对象。
    /// </remarks>
    public virtual object Operand
    {
      get
      {
        return this.operand;
      }
      set
      {
        this.operand = value;
      }
    }
    /// <summary>
    /// 获取类型操作数。
    /// </summary>
    public virtual Type TypeOperand
    {
      get
      {
        return this.operand as Type;
      }
      set
      {
        this.operand = value;
      }
    }
    /// <summary>
    /// 获取字段操作数。
    /// </summary>   
    public virtual FieldInfo FieldOperand
    {
      get
      {
        return this.operand as FieldInfo;
      }
      set
      {
        this.operand = value;
      }
    }
    /// <summary>
    /// 获取属性操作数。
    /// </summary>
    public virtual PropertyInfo PropertyOperand
    {
      get
      {
        return this.operand as PropertyInfo;
      }
      set
      {
        this.operand = value;
      }
    }
    /// <summary>
    /// 获取方法操作数。
    /// </summary>
    public virtual MethodBase MethodOperand
    {
      get
      {
        return this.operand as MethodBase;
      }
      set
      {
        this.operand = value;
      }
    }
    /// <summary>
    /// 获取成员操作数。
    /// </summary>
    public virtual MemberInfo MemberOperand
    {
      get
      {
        return this.operand as MemberInfo;
      }
      set
      {
        this.operand = value;
      }
    }
    /// <summary>
    /// 获取字符串操作数。
    /// </summary>
    public virtual string StringOperand
    {
      get
      {
        return this.operand as string;
      }
      set
      {
        this.operand = value;
      }
    }
    /// <summary>
    /// 获取SwitchDestination操作数。
    /// </summary>
    public virtual int[] SwitchesOperand
    {
      get
      {
        return this.operand as int[];
      }
      set
      {
        this.operand = value;
      }
    }
    /// <summary>
    /// 获取Address操作数。
    /// </summary>
    public virtual int AddressOperand
    {
      get
      {
        return this.GetLongOperand(this.operand);
      }
      set
      {
        this.operand = value;
      }
    }
    /// <summary>
    /// 获取签名操作数
    /// </summary>
    public virtual byte[] SignatureOperand
    {
      get
      {
        return this.operand as byte[];
      }
      set
      {
        this.operand = value;
      }
    }
    /// <summary>
    /// 判别是否具有类型操作数。
    /// </summary>
    public virtual bool HasTypeOperand
    {
      get
      {
        return this.TypeOperand != null;
      }
    }
    /// <summary>
    /// 判别是否具有字段操作数。
    /// </summary>
    public virtual bool HasFieldOperand
    {
      get
      {
        return this.FieldOperand != null;
      }
    }
    /// <summary>
    /// 判别是否具有属性操作数。
    /// </summary>
    public virtual bool HasPropertyOperand
    {
      get
      {
        return this.PropertyOperand != null;
      }
    }
    /// <summary>
    /// 判别是否具有方法操作数。
    /// </summary>
    public virtual bool HasMethodOperand
    {
      get
      {
        return this.MethodOperand != null;
      }
    }
    /// <summary>
    /// 判别是否具有成员操作数。
    /// </summary>
    public virtual bool HasMemberOperand
    {
      get
      {
        return this.MemberOperand != null;
      }
    }
    /// <summary>
    /// 判别是否具有字符串操作数。
    /// </summary>
    public virtual bool HasStringOperand
    {
      get
      {
        return this.StringToken != 0;
      }
    }
    /// <summary>
    /// 判别是否具有分支操作数。
    /// </summary>
    public virtual bool HasSwitchesOperand
    {
      get
      {
        return this.SwitchesOperand != null;
      }
    }
    public virtual bool HasSignatureOperand
    {
      get
      {
        return this.SignatureOperand != null;
      }
    }
    /// <summary>
    /// 获取类型Token。
    /// </summary>
    public virtual int TypeToken
    {
      get
      {
        if (!this.HasTypeOperand) throw new InvalidOperationException("Can not get Type token!");
        return this.TypeOperand.MetadataToken;
      }
    }
    /// <summary>
    /// 获取字段Token。
    /// </summary>
    public virtual int FieldToken
    {
      get
      {
        if (!this.HasFieldOperand) throw new InvalidOperationException("Can not get Field token!");
        return this.FieldOperand.MetadataToken;
      }
    }
    /// <summary>
    /// 获取属性Token。
    /// </summary>
    public virtual int PropertyToken
    {
      get
      {
        if (!this.HasPropertyOperand) throw new InvalidOperationException("Can not get Property token!");
        return this.PropertyOperand.MetadataToken;
      }
    }
    /// <summary>
    /// 获取方法Token。
    /// </summary>
    public virtual int MethodToken
    {
      get
      {
        if (!this.HasMethodOperand) throw new InvalidOperationException("Can not get Method token!");
        return this.MethodOperand.MetadataToken;
      }
    }
    /// <summary>
    /// 获取成员Token。
    /// </summary>
    public virtual int MemberToken
    {
      get
      {
        if (!this.HasMemberOperand) throw new InvalidOperationException("Can not get Member token!");
        return this.MemberOperand.MetadataToken;
      }
    }
    /// <summary>
    /// 获取字符串Token。
    /// </summary>
    /// <remarks>
    /// 由于无法单独获得字符串Token，
    /// 所以，如果直接从IL代码序列中读取
    /// 字符串Token，然后写回到原来的
    /// 代码序列中，那么我们必须先记录
    /// 这个Token。
    /// 注意：
    /// 若要修改字符串并更新它的Token，
    /// 请使用SetStringOperand方法。
    /// </remarks>
    public virtual int StringToken
    {
      get
      {
        return this.stringToken;
      }
    }
    /// <summary>
    /// 获取操作码类型。
    /// </summary>
    public virtual MsilOpCodeType OpcodeType
    {
      get
      {
        return this.opcode.OpCodeType;
      }
    }
    /// <summary>
    /// 获取操作数类型。
    /// </summary>
    public virtual MsilOperandType OperandType
    {
      get
      {
        return this.opcode.OperandType;
      }
    }
    public virtual MsilFlowControl FlowControl
    {
      get
      {
        return this.opcode.FlowControl;
      }
    }
    /// <summary>
    /// 获取操作码长度。
    /// </summary>
    public virtual int OpcodeSize
    {
      get
      {
        return this.opcode.Size;
      }
    }
    /// <summary>
    /// 获取操作数长度。
    /// </summary>
    public virtual int OperandSize
    {
      get
      {
        return this.GetOperandSize(this.OperandType,this.Operand);
      }
    }    
    /// <summary>
    /// 获取操作长度。
    /// </summary>
    public virtual int OperationSize
    {
      get
      {
        return this.OpcodeSize + OperandSize;
      }
    }
    /// <summary>
    /// 获取或者设置Agil操作在代码流中的位置。
    /// </summary>
    public virtual long OperationOffset
    {
      get
      {
        return this.offset;
      }
      set
      {
        this.offset = value;
      }
    }
    /// <summary>
    /// 获取Agil操作在代码流中的下一个位置。
    /// </summary>
    public virtual long NextOperationOffset
    {
      get
      {
        return this.OperationOffset + this.OperationSize;
      }
    }
    public virtual MethodBase Method
    {
      get
      {
        return this.method;
      }
    }
    public virtual bool HasMethod
    {
      get
      {
        return this.method != null;
      }
    }
    public virtual string Labels
    {
      get
      {
        return this.labels == null ? string.Empty : this.labels;
      }
      set
      {
        this.labels = value!=null ? value : string.Empty;
      }
    }
    public virtual string[] LabelList
    {
      get
      {
        return this.Labels.Split(new char[] { LabelSeparator }, StringSplitOptions.RemoveEmptyEntries);
      }
    }
    public virtual bool HasLabels
    {
      get
      {
        return !string.IsNullOrEmpty(this.labels);
      }
    }
    public virtual string VariableName
    {
      get
      {
        return this.variableName == null ? string.Empty : this.variableName;
      }
      set
      {
        this.variableName = value;
      }
    }
    public virtual bool HasVariableName
    {
      get
      {
        return !string.IsNullOrEmpty(this.variableName);
      }
    }
    public virtual Type[] PushStack
    {
      get
      {
        return this.pushStack == null ?
          this.pushStack = this.MsilOpcode.GetPushStack() :
          this.pushStack;
      }
    }
    public virtual Type[] PopStack
    {
      get
      {
        return this.popStack == null ?
          this.popStack = this.MsilOpcode.GetPopStack() :
          this.popStack;
      }
    }
    protected virtual MethodBody CurrentBody
    {
      get
      {
        return this.HasMethod ? this.Method.GetMethodBody() : null;
      }
    }

    protected virtual IList<LocalVariableInfo> LocalVariables
    {
      get
      {
        MethodBody currentBody = this.CurrentBody;

        return currentBody != null ? currentBody.LocalVariables : null;
      }
    }
   
    #endregion
    #region Constructors
    protected AgilOperation(MsilOpcode opcode):this(opcode,null)
    {
      if (opcode.OpValue.HasValue)
      {
        this.operand = opcode.opValue.Value;
      }
    }
    protected AgilOperation(MsilOpcode opcode, object operand)
      : this(opcode, operand, 0)
    {
    }
    protected AgilOperation(MsilOpcode opcode, object operand, int stringToken)
      : this(opcode, operand, stringToken, 0L)
    {
    }
    protected AgilOperation(MsilOpcode opcode, object operand, int stringToken, long offset)
    {
      this.opcode = opcode;
      this.operand = operand;
      this.stringToken = stringToken;
      this.offset = offset;
    }
    ~AgilOperation()
    {
      this.operand = null;
      this.stringToken = 0;
      this.offset = 0L;
    }
    #endregion
    #region Methods
    #region Public Misc
    /// <summary>
    /// 设定字符串操作数，并更新StringToken。
    /// </summary>
    /// <param name="newString">新的字符串</param>
    /// <param name="builder">模块构造器。</param>
    /// <returns>新字符串的Token。</returns>
    public virtual int SetStringOperand(string newString, ModuleBuilder builder)
    {
      this.operand = newString;
      return this.stringToken = this.GetStringToken(newString,this.stringToken,builder);
    }
    /// <summary>
    /// 复制操作。
    /// </summary>
    /// <returns>复制出的操作。</returns>
    public virtual AgilOperation Clone()
    {
      return of(this.opcode, this.operand);
    }
    /// <summary>
    /// 使用新的操作数进行复制操作。
    /// </summary>
    /// <param name="operand">新的操作数。</param>
    /// <returns>复制出的操作。</returns>
    public virtual AgilOperation Clone(object operand)
    {
      return of(this.opcode, operand);
    }
    /// <summary>
    /// 判别操作码是否匹配。
    /// </summary>
    /// <param name="code">操作码。</param>
    /// <param name="firstOpCode">设定是否判断第一个字节。如果为true，判断第一个字节，否则判断第二个字节。</param>
    /// <returns>如果匹配返回true，否则返回false。</returns>
    public virtual bool IsOpcodeMatched(byte code, bool firstOpCode)
    {
      return firstOpCode && this.FirstByte != MsilOpcode.FakeByte ? (code == this.FirstByte) : (code == this.SecondByte);
    }
    /// <summary>
    /// 判断操作码是否匹配指定AgilOperation。
    /// </summary>
    /// <param name="agil">指定AgilOperation。</param>
    /// <returns>如果匹配，返回true；否则返回false。</returns>
    public virtual bool IsOpcodeMatched(AgilOperation agil)
    {
      if (agil != null)
      {
        if (this.IsFake == false && agil.IsFake == false)
        {
          return this.IsOpcodeMatched(agil.Opcode);
        }
        else if (this.IsFake == true && agil.IsFake == true) 
        {
          return this.OpcodeName == agil.OpcodeName;
        }
      }
      return false;
    }
    /// <summary>
    /// 判断操作码是否匹配指定Opcode。
    /// </summary>
    /// <param name="agil">指定AgilOperation。</param>
    /// <returns>如果匹配，返回true；否则返回false。</returns>
    public virtual bool IsOpcodeMatched(MsilOpcode opcode)
    {
      return this.opcode.Equals(opcode);
    }
    /// <summary>
    /// 判断操作码是否匹配指定opcode。
    /// </summary>
    /// <param name="agil">指定opcode。</param>
    /// <returns>如果匹配，返回true；否则返回false。</returns>
    public virtual bool IsOpcodeMatched(short opcode)
    {
      return this.opcode.Value == opcode;
    }
    #endregion
    #region IL writing
    #region With ILGenerator
    /// <summary>
    /// 向ILGenerator发射AgilOperation的IL指令。
    /// </summary>
    /// <param name="ilGen">ILGenerator实例。</param>
    /// <remarks>
    /// 此方法尝试使用ILGenerator作为指令生成的目的地。
    /// 但由于ILGenerator使用内置的类型和标签机制，
    /// 此方法可能无法完全利用这些机制（例如Switch指令
    /// 无法在没有Label定义的前提下产生）。
    /// 注意，此类方法不发射虚拟操作（虚拟操作即IsFake为true）。
    /// </remarks>
    public virtual void Emit(ILGenerator ilGen, Module module)
    {
      if (ilGen == null) throw new ArgumentNullException("ilGen can not be null!");
      if (module == null) throw new ArgumentNullException("module can not be null!");

      this.EmitOperation(ilGen, module, this.OperandType);

    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="ilGen"></param>
    /// <param name="operandType"></param>
    /// <remarks>
    /// 注意，此类方法不发射虚拟操作（虚拟操作即IsFake为true）。
    /// </remarks>
    protected void EmitOperation(ILGenerator ilGen,Module module, MsilOperandType operandType)
    {
      if (!this.IsFake && ilGen!=null && module!=null)
      {
        try
        {
          switch (operandType)
          {
            case MsilOperandType.InlineBrTarget:
              ilGen.Emit(this.opcode, (int)this.operand);
              break;
            case MsilOperandType.InlineField:
              ilGen.Emit(this.opcode, this.FieldOperand);
              break;
            case MsilOperandType.InlineI:
              ilGen.Emit(this.opcode, (int)this.operand);
              break;
            case MsilOperandType.InlineI8:
              ilGen.Emit(this.opcode, (byte)this.operand);
              break;
            case MsilOperandType.InlineMethod:
              MethodBase method = this.MethodOperand;
              if (method is MethodInfo)
              {
                ilGen.Emit(this.opcode, method as MethodInfo);
              }
              else if (method is ConstructorInfo)
              {
                ilGen.Emit(this.opcode, method as ConstructorInfo);
              }
              else
              {
                throw new InvalidOperationException("Unknown MethodBase instance!");
              }
              break;
            case MsilOperandType.InlineNone:
              ilGen.Emit(this.opcode);
              break;
            case MsilOperandType.InlinePhi:           //UNKNOWN:ASSUME 0
              throw new ArgumentException("InlinePhi is not supported!");
            case MsilOperandType.InlineR:
              ilGen.Emit(this.opcode, (double)this.operand);
              break;
            case MsilOperandType.InlineSig:
              if (module is ModuleBuilder)
              {
                ModuleBuilder builder = module as ModuleBuilder;
                byte[] signature = this.SignatureOperand;
                if (signature != null)
                {
                  ilGen.Emit(this.opcode,builder.GetSignatureToken(signature, signature.Length).Token);
                }
              }
              break;
            case MsilOperandType.InlineString:
              //WE SHOULD WRITE STRING TOKEN HERE!
              ilGen.Emit(this.opcode, this.StringOperand);
              break;
            case MsilOperandType.InlineSwitch:        //There will be 4 + bytes.
              //SHOULD BE DONE ON THE UPPER LEVEL
              throw new InvalidOperationException(
                "Can not emit switches! You can use ILGenerator with Label[] to perform such task!"
                );
            case MsilOperandType.InlineTok:           //Token is      4 bytes
              ilGen.Emit(this.opcode, this.MemberToken);
              break;
            case MsilOperandType.InlineType:          //Type is       4 bytes
              ilGen.Emit(this.opcode, this.TypeOperand);
              break;
            case MsilOperandType.InlineVar:           //Inline Index  2 bytes
              ilGen.Emit(this.opcode, (short)this.operand);
              break;
            case MsilOperandType.ShortInlineBrTarget: //Short Target  1 byte
              ilGen.Emit(this.opcode, (byte)this.operand);
              break;
            case MsilOperandType.ShortInlineI:        //Short Integer 1 bytes
              ilGen.Emit(this.opcode, (byte)this.operand);
              break;
            case MsilOperandType.ShortInlineR:        //Short Real    4 bytes
              ilGen.Emit(this.opcode, (float)this.operand);
              break;
            case MsilOperandType.ShortInlineVar:      //Short Index   1 bytes
              ilGen.Emit(this.opcode, (byte)this.operand);
              break;
            default:
              throw new ArgumentException("Unknown OperandType!");

          }
        }
        catch (Exception ex)
        {
          throw new InvalidOperationException("Can not emit operation!", ex);
        }
      }
    }
    #endregion
    /// <summary>
    /// 向BinaryWriter发射AgilOperation的IL指令。
    /// </summary>
    /// <remarks>
    /// 注意，此类方法不发射虚拟操作（虚拟操作即IsFake为true）。
    /// </remarks>
    public virtual long Emit(BinaryWriter writer, Module module, long offset)
    {
      if (writer == null)
      {
        throw new ArgumentException("writer is not ready!");
      }

      if (!this.IsFake)
      {
        this.EmitOpcode(writer, this.OpcodeSize);
        this.EmitOperand(writer, this.OperandType, module);
      }

      return (this.offset = offset) + this.OperationSize;
    }
    protected virtual void EmitOpcode(BinaryWriter writer, int size)
    {
      if (size == 1)
      {
        writer.Write(this.FirstByte);
      }
      else if (size == 2)
      {
        writer.Write(this.FirstByte);
        writer.Write(this.SecondByte);
      }
      else
      {
        throw new ArgumentException("Invalid opcode size!");
      }
    }
    protected virtual void EmitSwitch(BinaryWriter writer, object operand)
    {
      if (operand is int[] )
      {
        int[] switches = operand as int[];
        if (switches != null)
        {
          writer.Write((uint)switches.Length);
          foreach (int sw in switches)
          {
            writer.Write((int)sw);
          }
        }
      }
      else
      {
        throw new ArgumentException("operand is not int[] or uint[]!");
      }
    }
    protected virtual void EmitInt8(BinaryWriter writer, object operand)
    {
      if (operand is byte || operand is sbyte)
      {
        writer.Write((byte)operand);
      }
      else
      {
        throw new ArgumentException("operand is not byte or sbyte!");
      }
    }
    protected virtual void EmitInt16(BinaryWriter writer, object operand)
    {
      if (operand is short || operand is ushort)
      {
        writer.Write((short)operand);
      }
      else
      {
        throw new ArgumentException("operand is not short or ushort!");
      }
    }
    protected virtual void EmitInt32(BinaryWriter writer, object operand)
    {
      if (operand is int || operand is uint)
      {
        writer.Write((int)operand);
      }
      else
      {
        throw new ArgumentException("operand is not int or uint!");
      }
    }
    protected virtual void EmitInt64(BinaryWriter writer, object operand)
    {
      if (operand is long || operand is long)
      {
        writer.Write((long)operand);
      }
      else
      {
        throw new ArgumentException("operand is not long or long!");
      }
    }
    protected virtual void EmitFloat32(BinaryWriter writer, object operand)
    {
      if (operand is float)
      {
        writer.Write((float)operand);
      }
      else
      {
        throw new ArgumentException("operand is not float!");
      }
    }
    protected virtual void EmitFloat64(BinaryWriter writer, object operand)
    {
      if (operand is double)
      {
        writer.Write((double)operand);
      }
      else
      {
        throw new ArgumentException("operand is not double!");
      }
    }
    protected virtual void EmitOperand(BinaryWriter writer, MsilOperandType operandType,Module module)
    {
      switch (operandType)
      {
        case MsilOperandType.InlineBrTarget:
          this.EmitInt32(writer, this.operand);
          break;
        case MsilOperandType.InlineField:
          this.EmitInt32(writer, this.FieldToken);
          break;
        case MsilOperandType.InlineI:
          this.EmitInt32(writer, this.operand);
          break;
        case MsilOperandType.InlineI8:
          this.EmitInt64(writer, this.operand);
          break;
        case MsilOperandType.InlineMethod:
          this.EmitInt32(writer, this.MethodToken);
          break;
        case MsilOperandType.InlineNone:
          break;
        case MsilOperandType.InlinePhi:           //UNKNOWN:ASSUME 0
          throw new ArgumentException("InlinePhi is not supported!");
        case MsilOperandType.InlineR:
          this.EmitFloat64(writer, this.operand);
          break;
        case MsilOperandType.InlineSig:
          if (module is ModuleBuilder)
          {
            ModuleBuilder builder = module as ModuleBuilder;
            byte[] signature = this.SignatureOperand;
            if (signature!=null)
            {
              this.EmitInt32(writer, builder.GetSignatureToken(signature, signature.Length).Token);
            }
          }
          break;
        case MsilOperandType.InlineString:
          //WE SHOULD WRITE STRING TOKEN HERE!
          this.EmitInt32(writer, 
            this.GetStringToken(this.StringOperand,this.stringToken,module as ModuleBuilder));
          //DYNAMIC BINDING TO TOKEN IF Module IS ModuleBuilder
          break;
        case MsilOperandType.InlineSwitch:        //There will be 4 + bytes.
          this.EmitSwitch(writer, operand);
          break;
        case MsilOperandType.InlineTok:           //Token is      4 bytes
          this.EmitInt32(writer, this.MemberToken);
          break;
        case MsilOperandType.InlineType:          //Type is       4 bytes
          this.EmitInt32(writer, this.TypeToken);
          break;
        case MsilOperandType.InlineVar:           //Inline Index  2 bytes
          this.EmitInt16(writer, this.operand);
          break;
        case MsilOperandType.ShortInlineBrTarget: //Short Target  1 byte
          this.EmitInt8(writer, this.operand);
          break;
        case MsilOperandType.ShortInlineI:        //Short Integer 2 bytes
          this.EmitInt16(writer, this.operand);
          break;
        case MsilOperandType.ShortInlineR:        //Short Real    4 bytes
          this.EmitFloat32(writer, this.operand);
          break;
        case MsilOperandType.ShortInlineVar:      //Short Index   2 bytes
          this.EmitInt16(writer, this.operand);
          break;
        default:
          throw new ArgumentException("Unknown OperandType!");
      }
    }
    #endregion
    #region IL reading
    protected virtual void Read(BinaryReader reader,Module module, MethodBase method, long offset, bool skipOpcode)
    {
      if ((this.method = method) != null)
      {
        module = method.Module;
      }
      if (module != null)
      {

        if (skipOpcode)
        {
          for (int i = 0; i < this.OpcodeSize; i++)
            reader.Read();
        }
        this.offset = offset;

        this.TranslateOperand(this.MsilOpcode,this.ReadOperand(reader, this.OperandType, module));
      }
    }
    protected virtual void TranslateOperand(MsilOpcode opcode,object operand)
    {
      if (opcode.OperandCat != MsilOperandCat.Ignored)
      {
        switch (opcode.OperandCat)
        {
          case MsilOperandCat.Argument:
            if (opcode.OpValue != null)
            {
              operand = opcode.OpValue;
            }
            this.VariableName = this.GetArgumentName(this.GetLongOperand(operand));
            break;
          case MsilOperandCat.Local:
            if (opcode.OpValue != null)
            {
              operand = opcode.OpValue;
            }
            this.VariableName = this.GetLocalVariableName(this.GetLongOperand(operand));
            break;
        }
      }
      //This means the opcode is a shortcut such as ldc.3.
      if (opcode.OpValue.HasValue)
      {
        this.operand = opcode.OpValue.Value;
      }
    }
    protected virtual object ReadOperand(BinaryReader reader, MsilOperandType operandType,Module module)
    {
      switch (operandType)
      {
        case MsilOperandType.InlineBrTarget:
          this.operand = this.ReadInt32(reader);
          break;
        case MsilOperandType.InlineField:
          this.operand = this.GetFieldInside(module,this.ReadInt32(reader));
          break;
        case MsilOperandType.InlineI:
          this.operand = this.ReadInt32(reader);
          break;
        case MsilOperandType.InlineI8:
          this.operand = this.ReadInt64(reader);
          break;
        case MsilOperandType.InlineMethod:
          this.operand = this.GetMethodInside(module,this.ReadInt32(reader));
          break;
        case MsilOperandType.InlineNone:
          this.operand = null;
          this.stringToken = 0;
          break;
        case MsilOperandType.InlinePhi:           //UNKNOWN:ASSUME 0
          throw new ArgumentException("InlinePhi is not supported!");
        case MsilOperandType.InlineR:
          this.operand = this.ReadFloat64(reader);
          break;
        case MsilOperandType.InlineSig:
          this.operand = this.GetSignatureInside(module,this.ReadInt32(reader));  //Signature
          break;
        case MsilOperandType.InlineString:
          this.operand = this.GetStringInside(module, 
            this.stringToken = this.ReadInt32(reader)
            );
          break;
        case MsilOperandType.InlineSwitch:        //There will be 4 + bytes.
          this.operand = this.ReadSwitches(reader);
          break;
        case MsilOperandType.InlineTok:           //Token is 4 bytes
          this.operand = this.GetMemberInside(module,this.ReadInt32(reader));
          break;
        case MsilOperandType.InlineType:          //Type is 4 bytes
          this.operand = this.GetTypeInside(module,this.ReadInt32(reader));
          break;
        case MsilOperandType.InlineVar:           //Inline Index  2 bytes
          this.operand = this.ReadInt16(reader);
          break;
        case MsilOperandType.ShortInlineBrTarget: //Short Target  1 byte
          this.operand = this.ReadInt8(reader);
          break;
        case MsilOperandType.ShortInlineI:        //Short Integer 1 bytes
          this.operand = this.ReadInt8(reader);
          break;
        case MsilOperandType.ShortInlineR:        //Short Real    4 bytes
          this.operand = this.ReadFloat32(reader);
          break;
        case MsilOperandType.ShortInlineVar:      //Short Index   1 byte
          this.operand = this.ReadInt8(reader);
          break;
        default:
          break;
      }
      return this.operand;
    }
    protected virtual int[] ReadSwitches(BinaryReader reader)
    {
      uint size = reader.ReadUInt32();

      int[] switches = new int[size];
      for (int i = 0; i < switches.Length; i++)
      {
        switches[i] = reader.ReadInt32();
      }
      return switches;
    }
    protected virtual byte ReadInt8(BinaryReader reader)
    {
      return reader.ReadByte();
    }
    protected virtual short ReadInt16(BinaryReader reader)
    {
      return reader.ReadInt16();
    }
    protected virtual int ReadInt32(BinaryReader reader)
    {
      return reader.ReadInt32();
    }
    protected virtual long ReadInt64(BinaryReader reader)
    {
      return reader.ReadInt64();
    }
    protected virtual float ReadFloat32(BinaryReader reader)
    {
      return reader.ReadSingle();
    }
    protected virtual double ReadFloat64(BinaryReader reader)
    {
      return reader.ReadDouble();
    }
    #endregion
    #region MetadataToken Convert
    protected virtual FieldInfo GetFieldInside(Module module, int metadataToken)
    {
      return module != null ? module.ResolveField(metadataToken, new Type[0], new Type[0]) : null;
    }
    protected virtual MethodBase GetMethodInside(Module module, int metadataToken)
    {
      return module != null ? module.ResolveMethod(metadataToken, new Type[0], new Type[0]) : null;
    }
    protected virtual Type       GetTypeInside  (Module module, int metadataToken)
    {
      return module != null ? module.ResolveType(metadataToken, new Type[0], new Type[0]) : null;
    }
    protected virtual MemberInfo GetMemberInside(Module module, int metadataToken)
    {
      return module != null ? module.ResolveMember(metadataToken) : null;
    }
    protected virtual String     GetStringInside(Module module, int metadataToken)
    {
      return module != null ? module.ResolveString(metadataToken) : null;
    }
    protected virtual byte[] GetSignatureInside(Module module, int metadataToken)
    {
      return module != null ? module.ResolveSignature(metadataToken) : new byte[0];
    }
    #endregion
    #region Protected Misc
    protected virtual int GetOperandSize(MsilOperandType operandType,object operand)
    {
      switch (operandType)
      {
        case MsilOperandType.InlineBrTarget:
          return 4;
        case MsilOperandType.InlineField:
          return 4;
        case MsilOperandType.InlineI:
          return 4;
        case MsilOperandType.InlineI8:
          return 8;
        case MsilOperandType.InlineMethod:
          return 4;
        case MsilOperandType.InlineNone:
          return 0;
        case MsilOperandType.InlinePhi:           //UNKNOWN:ASSUME 0
          return 0;
        case MsilOperandType.InlineR:
          return 8;
        case MsilOperandType.InlineSig:
          return 4;
        case MsilOperandType.InlineString:
          return 4;
        case MsilOperandType.InlineSwitch:        //There will be 4 + bytes.
          return 4 + ((operand is int[]) 
            ? (operand as int[]).Length * 4 : 0);
        case MsilOperandType.InlineTok:           //Token is 4 bytes
          return 4;
        case MsilOperandType.InlineType:          //Type is 4 bytes
          return 4;
        case MsilOperandType.InlineVar:           //Inline Index  2 bytes
          return 2;
        case MsilOperandType.ShortInlineBrTarget: //Short Target  1 byte
          return 1;
        case MsilOperandType.ShortInlineI:        //Short Integer 2 bytes
          return 1;
        case MsilOperandType.ShortInlineR:        //Short Real    4 bytes
          return 4;
        case MsilOperandType.ShortInlineVar:      //Short Index 2 bytes
          return 1;
        default:
          return 0;
      }
    }
    protected virtual int GetStringToken(string s, int oldtoken, ModuleBuilder builder)
    {
      if (builder != null)
      {
        StringToken sToken = builder.GetStringConstant(s);
        return sToken.Token;
      }
      else
      {
        return oldtoken;
      }
    }
    #endregion
    #region Overrides
    public virtual byte[] GetBytes(Module module)
    {
      byte[] bytes = null;
      using (MemoryStream memoryStream = new MemoryStream())
      {
        using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
        {
          this.Emit(binaryWriter, module, 0L);
        }
        bytes = memoryStream.ToArray();
      }
      return bytes;
    }
    public override string ToString()
    {
      return this.Format(this.offset, this.MsilOpcode, this.Operand,this.OperationSize,this.OperandType);
    }
    #region Formats
    protected virtual string Format(long offset, MsilOpcode opcode, object operand,int size,MsilOperandType opType)
    {
      return string.Format("{0}: {1} {2}", 
        this.FormatAddress(offset), 
        opcode.ToString(), 
        this.FormatOperand(offset,opcode,opType,operand,size)
        );
    }

    protected virtual string FormatOperand(long offset,MsilOpcode opcode, MsilOperandType opType,object operand,int size)
    {
      string op = string.Empty;

      if (operand != null)
      {
        switch (opType)
        {
          #region Default: NONE
          case MsilOperandType.InlinePhi:
            break;
          case MsilOperandType.InlineNone:
            break;
          #endregion
          #region Address:<ADDRESS>
          case MsilOperandType.InlineBrTarget:
          case MsilOperandType.ShortInlineBrTarget:
            op = this.FormatAddress(offset + size, this.GetLongOperand(operand));
            break;
          #endregion
          #region String: "STRING"
          case MsilOperandType.InlineString:
            op = this.FormatString(operand as string);
            break;
          #endregion
          #region Member: [Type::Member]
          case MsilOperandType.InlineField:
          case MsilOperandType.InlineMethod:
          case MsilOperandType.InlineType:
            MemberInfo member = operand as MemberInfo;
            if (member != null)
            {
              op = this.FormatMember(member);
            }
            break;
          #endregion
          #region Numbers: (Number)
          case MsilOperandType.InlineI8:
          case MsilOperandType.InlineI:
          case MsilOperandType.InlineR:
          case MsilOperandType.ShortInlineI:
          case MsilOperandType.ShortInlineR:
            op = this.FormatNumber(operand);
            break;
          #endregion
          #region Variable: [Variable Name],[%n%]
          case MsilOperandType.InlineVar:
          case MsilOperandType.ShortInlineVar:
            op = this.FormatVariable(this.VariableName);
            break;
          #endregion
          #region Signature: [#Signature#]
          case MsilOperandType.InlineSig:
            if (operand is byte[])
            {
              op = this.FormatSignature(operand as byte[]);
            }
            break;
          #endregion
          #region Token: [:Token:]
          case MsilOperandType.InlineTok:
            if (operand is int)
            {
              op = this.FormatToken((int)operand);
            }
            break;
          #endregion
          #region Switch:[%<ADDRESS>,<ADDRESS>... %]
          case MsilOperandType.InlineSwitch:
            op = this.FormatBranches(offset + size, operand as int[]);
            break;
          #endregion
        }
      }
      return op;
    }

    protected virtual string FormatToken(int token)
    {
      return string.Format("[:{0}:]", token);
    }
    protected virtual string FormatSignature(byte[] signature)
    {
      StringBuilder builder = new StringBuilder();
      if (builder != null && signature != null)
      {
        for (int i = 0; i < signature.Length; i++)
        {
          builder.AppendFormat("{0:X2}", signature[i]);
        }
      }
      return string.Format("[#{0}#]",builder.ToString());
    }
    protected virtual string FormatString(string s)
    {
      return s !=null ? string.Format("\"{0}\"", s) : string.Empty;
    }
    protected virtual string FormatNumber(object operand)
    {
      return operand != null ? string.Format("({0})", operand) : string.Empty;
    }

    protected virtual string FormatAddress(long current, long offset)
    {
      return this.FormatAddress(offset + current);
    }
    protected virtual string FormatAddress(long offset)
    {
      return string.Format("<{0:X8}>", offset);
    }
    protected virtual string FormatMember(MemberInfo member)
    {
      string format = string.Empty;

      if (member != null)
      {
        if (member is Type)
        {
          format = this.FormatType(member as Type);
        }
        else if (member is FieldInfo)
        {
          format = this.FormatField(member as FieldInfo);
        }
        else if (member is PropertyInfo)
        {
          format = this.FormatProperty(member as PropertyInfo);
        }
        else if (member is EventInfo)
        {
          format = this.FormatEvent(member as EventInfo);
        }
        else if (member is MethodBase)
        {
          format = this.FormatMethod(member as MethodBase);
        }
      }
      return format;
    }
    protected virtual string FormatVariable(string variableName)
    {
      return string.Format("[{0}]", variableName);
    }
    protected virtual string FormatBranches(long current, int[] branches)
    {
      string format = string.Empty;
      if (branches != null && branches.Length > 0)
      {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < branches.Length; i++)
        {
          if (i > 0)
          {
            builder.Append(", ");
          }
          builder.Append (this.FormatAddress(current,branches[i]));
        }
        format = string.Format("[%{0}%]", builder.ToString());
        builder = null;
      }
      return format;
    }

    protected virtual string FormatMethod(MethodBase method)
    {
      string format = string.Empty;
      if (method != null)
      {
        StringBuilder builder = new StringBuilder();
        builder.Append("(");

        ParameterInfo[] parameters = method.GetParameters();
        if (parameters != null)
        {
          for (int i = 0; i < parameters.Length; i++)
          {
            ParameterInfo parameter = parameters[i];
            if (parameter != null)
            {
              if (i > 0)
              {
                builder.Append(", ");
              }
              builder.Append(parameter.ParameterType.FullName);
            }
          }
        }
        builder.Append(")");
        Type returnType = method is MethodInfo ? (method as MethodInfo).ReturnType : null;

        string typeName = returnType != null ? returnType.FullName : "void";

        format = string.Format("[{0} {1}::{2}{3}]",
          typeName,
          method.DeclaringType.FullName,
          method.Name,
          builder.ToString()
          );
      }
      return format;
    }

    protected virtual string FormatType(Type type)
    {
      return type != null ? string.Format("[{0}]", type.FullName) : string.Empty;
    }

    protected virtual string FormatField(FieldInfo field)
    {
      return field != null ? string.Format("[{0}::{1}]", field.DeclaringType.FullName, field.Name) : string.Empty;
    }
    protected virtual string FormatProperty(PropertyInfo property)
    {
      return property!=null ? string.Format("[{0}::{1}]",property.DeclaringType.FullName, property.Name):string.Empty;
    }
    protected virtual string FormatEvent(EventInfo ev)
    {
      return ev != null ? string.Format("[{0}::{1}]", ev.DeclaringType.FullName, ev.Name) : string.Empty;
    }
    #endregion
    #region Helpers
    protected virtual int GetLongOperand(object operand)
    {
      if (operand != null && operand is ValueType)
      {
        if (operand is int||operand is uint)
        {
          return (int)operand;
        }
        else if (operand is short || operand is ushort)
        {
          return (short)operand;
        }
        else if (operand is byte || operand is sbyte)
        {
          return (byte)operand;
        }
      }
      return 0;
    }

    protected virtual string GetArgumentName(int index)
    {
      if (this.HasMethod)
      {
        index = this.CorrectIndex(index);

        ParameterInfo[] parameters = this.Method.GetParameters();
        if (parameters != null && parameters.Length > 0 && index>=0 && index< parameters.Length)
        {
          ParameterInfo parameter = parameters[index];
          return parameter != null ? parameter.Name : string.Empty;
        }
      }
      return string.Empty;
    }

    protected virtual string GetLocalVariableName(int index)
    {
      return this.NameLocalVariable(index);
    }
    protected virtual int CorrectIndex(int index)
    {
      return this.HasMethod && !this.Method.IsStatic ? index - 1 : index;
    }
    protected virtual string NameLocalVariable(int index)
    {
      return string.Format(".local_{0}", index);
    }
    #endregion
    #endregion
    #endregion
  }
}
